Don't use GValue in GtkCssValue
authorAlexander Larsson <alexl@redhat.com>
Thu, 8 Mar 2012 15:20:03 +0000 (16:20 +0100)
committerAlexander Larsson <alexl@redhat.com>
Thu, 8 Mar 2012 15:39:49 +0000 (16:39 +0100)
We now have complete coverage in the GtkCssValue API for type
handling, so drop the GValue from internal storage and just create
new ones when needed.

gtk/gtkcssvalue.c

index a3ea6d2dcc655de56b64a7e93315e66c493d79cb..367818116e9f693cc315353f7a74f7ea9b3b5e00 100644 (file)
 struct _GtkCssValue
 {
   volatile gint ref_count;
-  GValue g_value;
+  GType type;
+  union {
+    gpointer ptr;
+    gint gint;
+    double dbl;
+  } u;
 };
 
 G_DEFINE_BOXED_TYPE (GtkCssValue, _gtk_css_value, _gtk_css_value_ref, _gtk_css_value_unref)
 
 static GtkCssValue *
-_gtk_css_value_new (void)
+_gtk_css_value_new (GType type)
 {
   GtkCssValue *value;
 
   value = g_slice_new0 (GtkCssValue);
 
   value->ref_count = 1;
+  value->type = type;
 
   return value;
 }
@@ -62,9 +68,24 @@ _gtk_css_value_new_from_gvalue (const GValue *g_value)
     value = _gtk_css_value_new_from_number (g_value_get_boxed (g_value));
   else
     {
-      value = _gtk_css_value_new ();
-      g_value_init (&value->g_value, type);
-      g_value_copy (g_value, &value->g_value);
+      value = _gtk_css_value_new (type);
+
+      if (g_type_is_a (type, G_TYPE_OBJECT))
+       value->u.ptr = g_value_dup_object (g_value);
+      else if (g_type_is_a (type, G_TYPE_BOXED))
+       value->u.ptr = g_value_dup_boxed (g_value);
+      else if (g_type_is_a (type, G_TYPE_INT))
+       value->u.gint = g_value_get_int (g_value);
+      else if (g_type_is_a (type, G_TYPE_BOOLEAN))
+       value->u.gint = g_value_get_boolean (g_value);
+      else if (g_type_is_a (type, G_TYPE_ENUM))
+       value->u.gint = g_value_get_enum (g_value);
+      else if (g_type_is_a (type, G_TYPE_STRING))
+       value->u.ptr = g_value_dup_string (g_value);
+      else if (g_type_is_a (type, G_TYPE_DOUBLE))
+       value->u.dbl = g_value_get_double (g_value);
+      else
+       g_assert_not_reached ();
     }
 
   return value;
@@ -93,8 +114,24 @@ _gtk_css_value_new_take_gvalue (GValue *g_value)
     }
   else
     {
-      value = _gtk_css_value_new ();
-      value->g_value = *g_value;
+      value = _gtk_css_value_new (type);
+
+      if (g_type_is_a (type, G_TYPE_OBJECT))
+       value->u.ptr = g_value_get_object (g_value);
+      else if (g_type_is_a (type, G_TYPE_BOXED))
+       value->u.ptr = g_value_get_boxed (g_value);
+      else if (g_type_is_a (type, G_TYPE_INT))
+       value->u.gint = g_value_get_int (g_value);
+      else if (g_type_is_a (type, G_TYPE_BOOLEAN))
+       value->u.gint = g_value_get_boolean (g_value);
+      else if (g_type_is_a (type, G_TYPE_ENUM))
+       value->u.gint = g_value_get_enum (g_value);
+      else if (g_type_is_a (type, G_TYPE_STRING))
+       value->u.ptr = g_value_dup_string (g_value);
+      else if (g_type_is_a (type, G_TYPE_DOUBLE))
+       value->u.dbl = g_value_get_double (g_value);
+      else
+       g_assert_not_reached ();
     }
 
   return value;
@@ -110,17 +147,15 @@ _gtk_css_value_new_from_int (gint val)
     {
       if (singletons[val] == NULL)
        {
-         value = _gtk_css_value_new ();
-         g_value_init (&value->g_value, G_TYPE_INT);
-         g_value_set_int (&value->g_value, val);
+         value = _gtk_css_value_new (G_TYPE_INT);
+         value->u.gint = val;
          singletons[val] = value;
        }
       return _gtk_css_value_ref (singletons[val]);
     }
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, G_TYPE_INT);
-  g_value_set_int (&value->g_value, val);
+  value = _gtk_css_value_new (G_TYPE_INT);
+  value->u.gint = val;
 
   return value;
 }
@@ -130,9 +165,8 @@ _gtk_css_value_new_take_string (char *string)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, G_TYPE_STRING);
-  g_value_take_string (&value->g_value, string);
+  value = _gtk_css_value_new (G_TYPE_STRING);
+  value->u.ptr = string;
 
   return value;
 }
@@ -142,21 +176,28 @@ _gtk_css_value_new_from_string (const char *string)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, G_TYPE_STRING);
-  g_value_set_string (&value->g_value, string);
+  value = _gtk_css_value_new (G_TYPE_STRING);
+  value->u.ptr = g_strdup (string);
 
   return value;
 }
 
+static gpointer
+g_boxed_copy0 (GType         boxed_type,
+              gconstpointer src_boxed)
+{
+  if (src_boxed == NULL)
+    return NULL;
+  return g_boxed_copy (boxed_type, src_boxed);
+}
+
 GtkCssValue *
 _gtk_css_value_new_from_border (const GtkBorder *border)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GTK_TYPE_BORDER);
-  g_value_set_boxed (&value->g_value, border);
+  value = _gtk_css_value_new (GTK_TYPE_BORDER);
+  value->u.ptr = g_boxed_copy0 (GTK_TYPE_BORDER, border);
 
   return value;
 }
@@ -166,9 +207,8 @@ _gtk_css_value_new_take_pattern (cairo_pattern_t *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, CAIRO_GOBJECT_TYPE_PATTERN);
-  g_value_take_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (CAIRO_GOBJECT_TYPE_PATTERN);
+  value->u.ptr = v;
 
   return value;
 }
@@ -178,9 +218,8 @@ _gtk_css_value_new_from_pattern (const cairo_pattern_t *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, CAIRO_GOBJECT_TYPE_PATTERN);
-  g_value_set_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (CAIRO_GOBJECT_TYPE_PATTERN);
+  value->u.ptr = g_boxed_copy0 (CAIRO_GOBJECT_TYPE_PATTERN, v);
 
   return value;
 }
@@ -190,9 +229,8 @@ _gtk_css_value_new_take_shadow (GtkShadow *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GTK_TYPE_SHADOW);
-  g_value_take_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (GTK_TYPE_SHADOW);
+  value->u.ptr = v;
 
   return value;
 }
@@ -202,9 +240,8 @@ _gtk_css_value_new_take_font_description (PangoFontDescription *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, PANGO_TYPE_FONT_DESCRIPTION);
-  g_value_take_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (PANGO_TYPE_FONT_DESCRIPTION);
+  value->u.ptr = v;
 
   return value;
 }
@@ -214,9 +251,8 @@ _gtk_css_value_new_take_image (GtkCssImage *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GTK_TYPE_CSS_IMAGE);
-  g_value_take_object (&value->g_value, v);
+  value = _gtk_css_value_new (GTK_TYPE_CSS_IMAGE);
+  value->u.ptr = v;
 
   return value;
 }
@@ -233,9 +269,8 @@ _gtk_css_value_new_from_number (const GtkCssNumber *v)
     {
       if (zero_singleton == NULL)
        {
-         value = _gtk_css_value_new ();
-         g_value_init (&value->g_value, GTK_TYPE_CSS_NUMBER);
-         g_value_set_boxed (&value->g_value, v);
+         value = _gtk_css_value_new (GTK_TYPE_CSS_NUMBER);
+         value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_NUMBER, v);
          zero_singleton = value;
        }
       return _gtk_css_value_ref (zero_singleton);
@@ -251,18 +286,16 @@ _gtk_css_value_new_from_number (const GtkCssNumber *v)
       int i = round (v->value);
       if (px_singletons[i] == NULL)
        {
-         value = _gtk_css_value_new ();
-         g_value_init (&value->g_value, GTK_TYPE_CSS_NUMBER);
-         g_value_set_boxed (&value->g_value, v);
+         value = _gtk_css_value_new (GTK_TYPE_CSS_NUMBER);
+         value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_NUMBER, v);
          px_singletons[i] = value;
        }
 
       return _gtk_css_value_ref (px_singletons[i]);
     }
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GTK_TYPE_CSS_NUMBER);
-  g_value_set_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (GTK_TYPE_CSS_NUMBER);
+  value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_NUMBER, v);
 
   return value;
 }
@@ -272,9 +305,8 @@ _gtk_css_value_new_from_rgba (const GdkRGBA *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GDK_TYPE_RGBA);
-  g_value_set_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (GDK_TYPE_RGBA);
+  value->u.ptr = g_boxed_copy0 (GDK_TYPE_RGBA, v);
 
   return value;
 }
@@ -284,9 +316,8 @@ _gtk_css_value_new_from_color (const GdkColor *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GDK_TYPE_COLOR);
-  g_value_set_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (GDK_TYPE_COLOR);
+  value->u.ptr = g_boxed_copy0 (GDK_TYPE_COLOR, v);
 
   return value;
 }
@@ -296,9 +327,8 @@ _gtk_css_value_new_from_background_size (const GtkCssBackgroundSize *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GTK_TYPE_CSS_BACKGROUND_SIZE);
-  g_value_set_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (GTK_TYPE_CSS_BACKGROUND_SIZE);
+  value->u.ptr = g_boxed_copy0 (GTK_TYPE_CSS_BACKGROUND_SIZE, v);
 
   return value;
 }
@@ -308,9 +338,8 @@ _gtk_css_value_new_take_symbolic_color (GtkSymbolicColor *v)
 {
   GtkCssValue *value;
 
-  value = _gtk_css_value_new ();
-  g_value_init (&value->g_value, GTK_TYPE_SYMBOLIC_COLOR);
-  g_value_take_boxed (&value->g_value, v);
+  value = _gtk_css_value_new (GTK_TYPE_SYMBOLIC_COLOR);
+  value->u.ptr = v;
 
   return value;
 }
@@ -328,26 +357,62 @@ _gtk_css_value_ref (GtkCssValue *value)
 void
 _gtk_css_value_unref (GtkCssValue *value)
 {
+  GType type;
+
   if (value == NULL)
     return;
 
   if (!g_atomic_int_dec_and_test (&value->ref_count))
     return;
 
-  g_value_unset (&value->g_value);
+  type = value->type;
+
+  if (g_type_is_a (type, G_TYPE_OBJECT) && value->u.ptr != NULL)
+    g_object_unref (value->u.ptr);
+  else if (g_type_is_a (type, G_TYPE_BOXED) && value->u.ptr != NULL)
+    g_boxed_free (type, value->u.ptr);
+  else if (g_type_is_a (type, G_TYPE_STRING))
+    g_free (value->u.ptr);
+
   g_slice_free (GtkCssValue, value);
 }
 
 GType
 _gtk_css_value_get_content_type (GtkCssValue *value)
 {
-  return G_VALUE_TYPE (&value->g_value);
+  return value->type;
 }
 
 gboolean
 _gtk_css_value_holds (GtkCssValue *value, GType type)
 {
-  return G_VALUE_HOLDS (&value->g_value, type);
+  return g_type_is_a (value->type, type);
+}
+
+static void
+fill_gvalue (GtkCssValue *value,
+            GValue      *g_value)
+{
+  GType type;
+
+  type = value->type;
+
+  if (g_type_is_a (type, G_TYPE_OBJECT))
+    g_value_set_object (g_value, value->u.ptr);
+  else if (g_type_is_a (type, G_TYPE_BOXED))
+    g_value_set_boxed (g_value, value->u.ptr);
+  else if (g_type_is_a (type, G_TYPE_INT))
+    g_value_set_int (g_value, value->u.gint);
+  else if (g_type_is_a (type, G_TYPE_BOOLEAN))
+    g_value_set_boolean (g_value, value->u.gint);
+  else if (g_type_is_a (type, G_TYPE_ENUM))
+    g_value_set_enum (g_value, value->u.gint);
+  else if (g_type_is_a (type, G_TYPE_STRING))
+    g_value_set_string (g_value, value->u.ptr);
+  else if (g_type_is_a (type, G_TYPE_DOUBLE))
+    g_value_set_double (g_value, value->u.dbl);
+  else
+    g_assert_not_reached ();
 }
 
 void
@@ -356,8 +421,8 @@ _gtk_css_value_init_gvalue (GtkCssValue *value,
 {
   if (value != NULL)
     {
-      g_value_init (g_value, G_VALUE_TYPE (&value->g_value));
-      g_value_copy (&value->g_value, g_value);
+      g_value_init (g_value, value->type);
+      fill_gvalue (value, g_value);
     }
 }
 
@@ -365,13 +430,18 @@ void
 _gtk_css_value_to_gvalue (GtkCssValue *value,
                          GValue      *g_value)
 {
-  if (G_VALUE_TYPE (&value->g_value) == G_VALUE_TYPE (g_value))
-    g_value_copy (&value->g_value, g_value);
-  else if (g_value_type_transformable (G_VALUE_TYPE (&value->g_value), G_VALUE_TYPE (g_value)))
-    g_value_transform (&value->g_value, g_value);
+  if (value->type == G_VALUE_TYPE (g_value))
+    fill_gvalue (value, g_value);
+  else if (g_value_type_transformable (value->type, G_VALUE_TYPE (g_value)))
+    {
+      GValue v = G_VALUE_INIT;
+      _gtk_css_value_init_gvalue (value, &v);
+      g_value_transform (&v, g_value);
+      g_value_unset (&v);
+    }
   else
     g_warning ("can't convert css value of type `%s' as value of type `%s'",
-              G_VALUE_TYPE_NAME (&value->g_value),
+              g_type_name (value->type),
               G_VALUE_TYPE_NAME (g_value));
 }
 
@@ -385,159 +455,161 @@ GtkCssSpecialValue
 _gtk_css_value_get_special_kind  (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_SPECIAL_VALUE), 0);
-  return g_value_get_enum (&value->g_value);
+  return value->u.gint;
 }
 
 GtkCssNumber *
 _gtk_css_value_get_number  (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_NUMBER), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkSymbolicColor *
 _gtk_css_value_get_symbolic_color  (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_SYMBOLIC_COLOR), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 int
 _gtk_css_value_get_int (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_INT), 0);
-  return g_value_get_int (&value->g_value);
+  return value->u.gint;
 }
 
 double
 _gtk_css_value_get_double (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_DOUBLE), 0);
-  return g_value_get_double (&value->g_value);
+  return value->u.dbl;
 }
 
 const char *
 _gtk_css_value_get_string (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_STRING), 0);
-  return g_value_get_string (&value->g_value);
+  return value->u.ptr;
 }
 
 gpointer
 _gtk_css_value_dup_object (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_OBJECT), NULL);
-  return g_value_dup_object (&value->g_value);
+  if (value->u.ptr)
+    return g_object_ref (value->u.ptr);
+  return NULL;
 }
 
 gpointer
 _gtk_css_value_get_object (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_OBJECT), NULL);
-  return g_value_get_object (&value->g_value);
+  return value->u.ptr;
 }
 
 gpointer
 _gtk_css_value_get_boxed (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_BOXED), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 const char **
 _gtk_css_value_get_strv (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, G_TYPE_STRV), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkCssImage *
 _gtk_css_value_get_image (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_IMAGE), NULL);
-  return g_value_get_object (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkBorderStyle
 _gtk_css_value_get_border_style (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_BORDER_STYLE), 0);
-  return g_value_get_enum (&value->g_value);
+  return value->u.gint;
 }
 
 GtkCssBackgroundSize *
 _gtk_css_value_get_background_size (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BACKGROUND_SIZE), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkCssBorderImageRepeat *
 _gtk_css_value_get_border_image_repeat (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkCssBorderCornerRadius *
 _gtk_css_value_get_border_corner_radius (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 PangoFontDescription *
 _gtk_css_value_get_font_description (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_FONT_DESCRIPTION), 0);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 PangoStyle
 _gtk_css_value_get_pango_style (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_STYLE), 0);
-  return g_value_get_enum (&value->g_value);
+  return value->u.gint;
 }
 
 PangoVariant
 _gtk_css_value_get_pango_variant (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_VARIANT), 0);
-  return g_value_get_enum (&value->g_value);
+  return value->u.gint;
 }
 
 PangoWeight
 _gtk_css_value_get_pango_weight (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, PANGO_TYPE_WEIGHT), 0);
-  return g_value_get_enum (&value->g_value);
+  return value->u.gint;
 }
 
 GdkRGBA *
 _gtk_css_value_get_rgba (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GDK_TYPE_RGBA), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 cairo_pattern_t *
 _gtk_css_value_get_pattern (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, CAIRO_GOBJECT_TYPE_PATTERN), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkGradient *
 _gtk_css_value_get_gradient (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_GRADIENT), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }
 
 GtkShadow *
 _gtk_css_value_get_shadow (GtkCssValue *value)
 {
   g_return_val_if_fail (_gtk_css_value_holds (value, GTK_TYPE_SHADOW), NULL);
-  return g_value_get_boxed (&value->g_value);
+  return value->u.ptr;
 }